#ifndef __SYSY_LIB_H__
#define __SYSY_LIB_H__

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
#include <uuid/uuid.h>

#include "array_table.h"
#include "hash_table.h"
#include "nls.h"
#include "sysy_conf.h"
#include "yid.h"
#include "ylock.h"
#include "ypath.h"
//#include "tpool.h"
#include "heap.h"
#include "sysutil.h"
#include "mini_hashtb.h"

#define ENABLE_YMALLOC_STAT 0

typedef struct {
        uint32_t addr;
        uint32_t port;
} addr_t;

/* auth.c */
extern int chech_auth_shadow(const char *user, const char *passwd);

/* array_table.c */
extern atable_t array_create_table(int (*compare_func)(void *, void *),
                                   int max_array);
extern int array_table_get_nr(atable_t);
extern int array_table_get_max(atable_t);
extern int array_table_insert_empty(atable_t, void *value);
extern int array_table_insert(atable_t t, int no, void *value);
extern void *array_table_find(atable_t, int no, void *comparator);
extern int array_table_remove(atable_t, int no, void *comparator, void **value);
extern void array_table_destroy(atable_t);

/* cmp.c */
extern int int_cmp(const void *key, const void *data);
extern int int64_cmp(const void *key, const void *data);
extern int verid64_cmp(const verid64_t *key, const verid64_t *data);
extern int verid64_void_cmp(const void *key, const void *data);
int verid64_equal(const verid64_t *id1, const verid64_t *id2);
int verid64_void_equal(const void *key, const void *data);

/*md5.c  */
typedef unsigned char *POINTER; /* POINTER defines a generic pointer type */
typedef unsigned short int UINT2; /* UINT2 defines a two byte word */
typedef unsigned long int UINT4; /* UINT4 defines a four byte word */

/* crc32.c */
#define crc32_init(crc) ((crc) = ~0U)
extern int crc32_stream(uint32_t *_crc, const char *buf, uint32_t len);
extern uint32_t crc32_stream_finish(uint32_t crc);
uint32_t crc32_sum(const void *ptr, uint32_t len);

/* crcrs.c */
extern void crcrs_init(void);

/* daemon.c */

extern int nofile_max;
int daemon_update(const char *key, const char *value);
int daemon_pid(const char *path);
int daemon_lock(const char *key);
extern int daemonlize(int daemon, int maxcore, char *chr_path, int *preservefds, int count);
extern int set_environment(void);

/* hash.c */
extern uint32_t hash_str(const char *str);
extern uint32_t hash_mem(const void *mem, int size);

/* lock.c */
extern int sy_rwlock_init(sy_rwlock_t *rwlock, const char *name);
extern int sy_rwlock_destroy(sy_rwlock_t *rwlock);
extern int sy_rwlock_rdlock(sy_rwlock_t *rwlock);
extern int sy_rwlock_tryrdlock(sy_rwlock_t *rwlock);
extern int sy_rwlock_wrlock(sy_rwlock_t *rwlock);
extern int sy_rwlock_trywrlock(sy_rwlock_t *rwlock);
extern void sy_rwlock_unlock(sy_rwlock_t *rwlock);
extern int sy_rwlock_timedwrlock(sy_rwlock_t *rwlock, int sec);

/* mem.c */

int ymalloc(void **ptr, size_t size);
int yrealloc(void **_ptr, size_t size, size_t newsize);
int yfree(void **ptr);

int ymalloc1(void **ptr, size_t size);
int yfree1(void **ptr);

void ymalloc_print();

// #define ymalloc(pp, size) ymalloc0((pp), (size))
// #define yfree(pp) yfree0((pp))

/* nls.c */
extern int nls_getable(char *charset, struct nls_table **);

/* path.c */
#define YLIB_ISDIR 1
#define YLIB_NOTDIR 0

#define YLIB_DIRCREATE 1
#define YLIB_DIRNOCREATE 0

extern int cascade_iterator(char *path, void *args, int (*callback)(const char *path, void *args));
extern void rorate_id2path(char *path, uint32_t pathlen, uint32_t pathlevel,
                           const char *id);
extern void cascade_id2path(char *path, uint32_t pathlen, uint64_t id);
extern int cascade_path2idver(const char *path, uint64_t *id,
                              uint32_t *version);
extern int df_iterate_tree(const char *basedir, df_dir_list_t *,
                           void (*func)(void *));

/* from path.c */
int path_validate(const char *path, int isdir, int dircreate);
int path_normalize(const char *path, char *path2);
int path_getvolume(char *path, int *is_vol, char *vol_name);

int path_drophead(char *path);
int path_droptail(char *path, int len);

int rmrf(const char *path);

int path_encode(const char *pool, const char *protocol, const char *vol, const char *snap, char *path);
int path_encode2(const char *pool, const char *protocol, char *path);
int path_encode3(const char *pool, const char *protocol, const char *vol, char *path);

int path_decode(const char *path, char *pool, char *protocol, char *vol, char *snap);

int path_head(const char *path, int sep, char *head, char *path2);
int path_split(const char *path, char *pool, char *path2);

int path_access(const char *path);
/* stat.c */
extern void mode_to_permstr(uint32_t mode, char *perms);
extern void stat_to_datestr(struct stat *, char *date);

/* str.c */
extern int str_replace_char(char *str, char from, char to);
extern int str_replace_str(char *str, char *from, char *to);
extern int str_upper(char *str);
extern unsigned int str_octal_to_uint(const char *str);

/*
 * sends at-most the specified # of byets.
 * @retval Returns the result of calling _send() on right or -errno.
 */
extern int sy_send(int sd, const char *buf, uint32_t buflen);
/*
 * Receives at-most the specified # of bytes.
 * @retval Returns the result of calling _recv() on right or -errno.
 */
extern int sy_recv(int sd, char *buf, uint32_t buflen);
/*
 * Peek to see if any data is available. This call will not remove the data
 * from the underlying socket buffers.
 * @retval Returns # of bytes copied in on right or -errno.
 */
extern int sy_peek(int sd, char *buf, uint32_t buflen);
extern int sy_close(int fd);
extern void sy_close_failok(int fd);
extern void sy_msleep(uint32_t milisec);
extern int sy_isidle(void);

/* var.c */
/* args ends with -1 */
extern int varsum(int first, ...);

#define SOCK_MAX 10

typedef struct {
        uint32_t port;
        char name[MAX_NAME_LEN];
        int count;
        uint32_t addrs[SOCK_MAX];
} addr1_t;

#define MAX_NODEID_LEN (40)

/* sysutil.c */

typedef void *(*thread_func)(void *);

int sy_thread_create(thread_func fn, void *arg);
#define sy_pthread_create sy_thread_create

int sy_thread_create2(thread_func fn, void *arg, const char *name);

uint64_t fastrandom();
int fastrandom_private_init();
int fastrandom_init();

typedef struct {
        uint32_t chknum;
        uint32_t cursor;
        uint32_t step;
        uint32_t idx;
} generator_t;

void chkid_generator_init(generator_t *gen, uint32_t chknum, uint32_t step);
int chkid_generator(generator_t *gen, uint32_t *_idx);

#endif /* __SYSY_LIB_H__ */
